package com.polaris.live.viewmodel.party.base

import androidx.core.os.bundleOf
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase
import com.polaris.live.common.cacha.CacheUtil
import com.polaris.live.common.constant.AppConst
import com.polaris.live.common.constant.BizEventConst
import com.polaris.live.common.constant.CommonConst
import com.polaris.live.common.event.EventMessage
import com.polaris.live.common.manager.CoroutineScopeManager
import com.polaris.live.common.mvvm.viewmodel.BaseViewModel
import com.polaris.live.common.network.AppException
import com.polaris.live.common.network.launchLoading
import com.polaris.live.common.network.request
import com.polaris.live.common.network.requestLoading
import com.polaris.live.common.network.state.ResultState
import com.polaris.live.common.util.JsonUtils
import com.polaris.live.common.util.LogExt
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.common.util.ViewUtils
import com.polaris.live.constant.LiveConst
import com.polaris.live.im.sfs.COMMAND_LIVE_PUBLIC_SCREEN
import com.polaris.live.im.sfs.PARTY_LIVESITEMICSWITCH
import com.polaris.live.im.sfs.bean.live.LivePublicScreenMessage
import com.polaris.live.im.sfs.bean.live.LiveSiteMicSwitchMessage
import com.polaris.live.im.sfs.core.SmartFoxManager
import com.polaris.live.im.sfs.core.SmartFoxQueueManager
import com.polaris.live.interface_bag.S3UploadCallback
import com.polaris.live.manager.AppConfigManager
import com.polaris.live.net.gameService
import com.polaris.live.net.liveService
import com.polaris.live.net.payerService
import com.polaris.live.net.userService
import com.polaris.live.popup.GlobalPopupManager
import com.polaris.live.resp.back_resp.GameGroupVoResp
import com.polaris.live.resp.back_resp.GameRankResp
import com.polaris.live.resp.back_resp.LiveConsumeUserResp
import com.polaris.live.resp.back_resp.LiveEmojiResp
import com.polaris.live.resp.back_resp.PayerLampLotteryResp
import com.polaris.live.resp.back_resp.ScreenshotStrategyVo
import com.polaris.live.resp.back_resp.SendMessageBarrageNumberResp
import com.polaris.live.resp.back_resp.UserBackpackBarrageNumberResp
import com.polaris.live.resp.bean.SendEmojiBean
import com.polaris.live.resp.event.BackgroundEvent
import com.polaris.live.resp.go_resp.ScreenshotLoadBean
import com.polaris.live.resp.go_resp.TaskMicRequest
import com.polaris.live.translation.R
import com.polaris.live.ui.game.GameFromType
import com.polaris.live.ui.game.GameUtils
import com.polaris.live.ui.party.utils.GiftGivingAnimationProxy.Companion.CLEAR_TIME
import com.polaris.live.utils.image.ImageUtils
import com.polaris.live.utils.postEvent
import com.polaris.live.utils.zego.LiveEngineManage
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus

/**
 *BasePartyFragmentModel
 * @author Created by 天晴 on 2024/3/8 17:08
 * @since 1.0.0
 **/
open class BasePartyFragmentModel : BaseViewModel() {

    /**
     * 开关麦
     */
    fun siteMicSwitch(anchorId: Long, open: Boolean) {
        launchLoading {
            try {
                SmartFoxQueueManager.sendLiveMessage(
                    PARTY_LIVESITEMICSWITCH,
                    LiveSiteMicSwitchMessage(anchorId, open)
                )
            } catch (t: Throwable) {
                ToastGravity.showGravity(t.message)
            }
        }
    }

    private var activitiesCount = 0
    val activitiesScrollLiveData = MutableLiveData<Int>() //请求活动滚动信息刷新

    //直播获取顶部消费列表
    val liveUserCountLiveData = MutableLiveData<Int>()
    val liveConsumeLiveData = MutableLiveData<Pair<Long, LiveConsumeUserResp>>()
    private var liveConsumeJob: Job? = null
    fun launchConsumeUser(liveId: Long) {
        liveConsumeJob?.cancel()
        liveConsumeJob = viewModelScope.launch {
            try {
                while (isActive) {
                    request({ liveService.liveConsumeV2(liveId) }, {
                        liveConsumeLiveData.value = liveId to it
                    })

                    SmartFoxManager.getLiveRoom()?.userCount?.also {
                        liveUserCountLiveData.value = it
                    }

                    delay(LiveConst.PARTY_LIST_TIME)
                    activitiesCount++

                    if (activitiesCount % 3 == 0) {
                        activitiesScrollLiveData.value = activitiesCount
                    }

                }
            } finally {
                if (liveConsumeJob == coroutineContext[Job]) {
                    liveConsumeJob = null
                }
            }
        }
    }

    /**
     * 取消定时任务
     */
    fun stopConsumeJob() {
        liveConsumeJob?.cancel()
    }

    private var clearTimeJob: Job? = null

    val clearTimeLiveData = MutableLiveData<Int>()

    /**
     * 开始清除送礼View工作线程
     */
    fun openClearTimeJob() {
        clearTimeJob?.cancel()
        clearTimeJob = viewModelScope.launch {
            try {
                while (isActive) {
                    delay(CLEAR_TIME)
                    clearTimeLiveData.value = (clearTimeLiveData.value ?: 0) + 1
                }
            } finally {
                if (clearTimeJob == coroutineContext[Job]) {
                    clearTimeJob = null
                }
            }
        }
    }

    /**
     * 取消定时任务
     */
    fun stopClearTimeJob() {
        clearTimeJob?.cancel()
    }

    //弹幕信息更新
    val barrageNumberLiveData = MutableLiveData<ResultState<UserBackpackBarrageNumberResp>>()

    //发送公屏消息
    fun sendPublicMessage(message: LivePublicScreenMessage) {
        viewModelScope.launch {
            try {
                val data = SmartFoxQueueManager.sendLiveMessage(COMMAND_LIVE_PUBLIC_SCREEN, message)
                if (message.type == 1) {//发送的弹幕
                    if (!data.ext.isNullOrEmpty()) {
                        val bean = JsonUtils.fromJson<SendMessageBarrageNumberResp>(data.ext)
                        bean?.barrageNumber?.let {
                            barrageNumberLiveData.value = ResultState.onAppSuccess(it)
                        }
                    }
                    ToastGravity.showGravity(R.string.published_successfully)
                }
            } catch (t: Throwable) {
                if (t is AppException) {
                    if (t.errCode == CommonConst.ErrorCode.SENDGIFT) {
                        ViewUtils.getAliveTopActivity()?.let { con ->
                            GlobalPopupManager.showRechargePopup(
                                con,
                                this@BasePartyFragmentModel,
                                isNeedBottom = true, onRechargeOk = {
                                    EventBus.getDefault().post(EventMessage(BizEventConst.INFO_UPDATA))
                                })
                        }

                    }
                }
                ToastGravity.showGravity(t.message)
            }
        }
    }

    //获取游戏列表
    val gameLiveData = MutableLiveData<ResultState<List<GameGroupVoResp>>>()
    fun getGameList(liveId: Long) {
        if (GameUtils.getLiveCacheGameList().isNullOrEmpty()) {
            request({ gameService.getGameList(GameFromType.LIVE) }, gameLiveData)
        } else {
            gameRank(liveId)
        }
    }

    //游戏排行榜
    val gameRankLiveData = MutableLiveData<ResultState<List<GameRankResp>>>()
    private var gameRankJob: Job? = null
    fun gameRank(liveId: Long) {
        if (GameUtils.getShowWinPop(liveId)) { //游戏列表不为空进行弹窗
            gameRankJob = viewModelScope.launch {
                delay(GameUtils.MAX_LAST_POP_TIME)
                request({ gameService.getGameRank() }, gameRankLiveData)
            }
        }
    }

    fun cancelGameRankJob() {
        gameRankJob?.cancel()
        gameRankJob = null
    }

    //emoji列表
    val mEmojiListLiveData = MutableLiveData<ResultState<List<LiveEmojiResp>>>()
    fun emojiList() {
        request({ liveService.liveEmoji() }, mEmojiListLiveData)
    }

    //发送emoji表情
    fun sendEmoji(emojiId: Long, liveId: Long) {
        requestLoading({ liveService.sendEmoji(SendEmojiBean(emojiId, liveId)) }, {})
    }

    //截图上传
    private var screenshotJob: Job? = null
    fun launchScreenshot(
        liveId: Long,
        liveStartTime: Long,
        screenshotStrategy: ScreenshotStrategyVo,
    ) {
        cancelScreenshotJob()

        val rules = screenshotStrategy.rules
        if (rules.isEmpty()) {
            return
        }
        //获取最大延迟
        val maxInterval = rules.entries.maxBy { it.key }.value * 1000

        screenshotJob = viewModelScope.launch {
            try {
                while (isActive) {
                    val startTime = System.currentTimeMillis()

                    withContext(CoroutineScopeManager.ioDispatcher) {
                        try {
                            takeScreenshot(liveId)
                        } catch (_: Throwable) {
                        }
                    }

                    val tickDuration = System.currentTimeMillis() - startTime

                    val interval =
                        computeNextDelay(liveStartTime, screenshotStrategy) ?: maxInterval
                    val delayTime = interval - tickDuration
                    if (delayTime > 0) {
                        delay(delayTime)
                    }
                }
            } finally {
                if (screenshotJob == coroutineContext[Job]) {
                    screenshotJob = null
                }
            }
        }
    }

    /**
     * 取消上传截图
     */
    fun cancelScreenshotJob() {
        screenshotJob?.cancel()
        screenshotJob = null
    }

    private fun computeNextDelay(
        liveStartTime: Long,
        screenshotStrategy: ScreenshotStrategyVo,
    ): Long? {
        //先计算当前是第几分钟
        val intervalMinute = (CacheUtil.getServerTime() - liveStartTime) / 1000 / 60

        return screenshotStrategy.rules[(intervalMinute + 1).toString()]?.let { it * 1000L }
    }

    private fun takeScreenshot(liveId: Long) {
        takeScreenshot(AppConst.UpLoad.VIDEO_PARTY_SCREENSHOT) {
            screenshotUpload(CommonConst.Screenshot.VIDEO_PARTY, liveId, it)
        }
    }

    private fun screenshotUpload(type: Int, objectId: Long, path: String) {
        request({ liveService.screenshotUpLoad(ScreenshotLoadBean(type, objectId, path)) }, {})
    }

    private var mScreenshotErrorTime: Int = 0
    private fun takeScreenshot(type: Int, block: (String) -> Unit) {
        LiveEngineManage.getEngine()?.takePublishStreamSnapshot { errorCode, image ->
            if (errorCode == 0 && image != null) {

                if (ImageUtils.isBitmapEmpty(image)) {
                    if (mScreenshotErrorTime++ <= 3) {
                        viewModelScope.launch {
                            delay(1000)
                            takeScreenshot(type, block)
                        }
                    }
                    return@takePublishStreamSnapshot
                }

                mScreenshotErrorTime = 0

                ImageUtils.s3Upload(image, type, callback = object : S3UploadCallback {
                    override fun onSuccess(url: String, size: Pair<Int, Int>?) {
                        block(url)
                    }

                    override fun onFailure(t: Throwable) {
                        LogExt.logE("--net", t)

                        Firebase.analytics.postEvent(
                            "screenshot_error", bundleOf(
                                "errorMessage" to t.message
                            )
                        )
                    }
                })
            } else {
                Firebase.analytics.postEvent(
                    "screenshot_error", bundleOf(
                        "errorCode" to errorCode
                    )
                )
            }
        }
    }

    private var killJob: Job? = null
    fun killActivityTimeout(time: Long) {
        stopKillActivityTimeout()
        killJob = viewModelScope.launch {
            try {
                delay(time)
                EventBus.getDefault().post(BackgroundEvent(0))
            } finally {
                if (killJob == coroutineContext[Job]) {
                    killJob = null
                }
            }
        }
    }

    fun stopKillActivityTimeout() {
        killJob?.cancel()
        killJob = null
    }

    /**
     * 获取礼物红点
     */
    //获取游戏状态
    val mBackGiftRedData = MutableLiveData<ResultState<Boolean>>()
    fun getBackGiftRed() {
        request(
            { userService.getHaveNewBackpack() }, mBackGiftRedData
        )
    }

    private var lastTime = 0L
    private val intervalTime: Long by lazy {
        AppConfigManager.getConfig(CommonConst.Configs.taskMicAudioReportInterval)?.toLongOrNull() ?: 5000L
    }

    /**
     * 麦位音浪上报
     */
    fun taskMicReport(liveDetailId: String, siteId: Long, soundLevel: String) {
        val nowTime = System.currentTimeMillis()
        if (nowTime - lastTime > intervalTime) {
            request(
                { userService.taskMicReport(TaskMicRequest(liveDetailId, siteId, soundLevel)) }, {
                    lastTime = nowTime
                }
            )
        }

    }

    //神灯抽奖
    val mLampLotteryLiveData = MutableLiveData<ResultState<PayerLampLotteryResp>>()
    fun lampLottery(userId: Long, index: Long) {
        request({ payerService.getLampLottery(userId, index) }, mLampLotteryLiveData)
    }
}